source ~/build-env.sh
work_dir=`pwd`
boot_img="boot.img"
tool_dir=$work_dir/tools
atf_dir=$work_dir/arm-trusted-firmware
public_key_path=$work_dir/public_key.dts
rkbin_dir=$work_dir/rkbin
uboot_dir=$work_dir/u-boot
key_dir=$work_dir/keys
out_dir=$work_dir/output
update_img_build_dir=$work_dir/forlinx-prebuild
make_config=evb-rk3568_defconfig
platform=rk3568
dts_dir=$uboot_dir/dts/upstream/src/arm64/
uboot_config_dir=$uboot_dir/configs

if [ ! -d "$out_dir" ]; then
  # 创建文件夹
  mkdir "$out_dir"
  echo "已创建 $out_dir 文件夹"
else
  echo "$out_dir 文件夹已存在"
fi

create_empty_dtb(){
    echo "/dts-v1/;" > pub-key.dts
    echo "/ {" >> pub-key.dts
    echo "        model = \"\";" >> pub-key.dts
    echo "        compatible = \"\";" >> pub-key.dts
    echo "};" >> pub-key.dts
    #将dts 转换成dtb
    dtc -I dts -O dtb pub-key.dts -o ./pub-key.dtb
}

#编译arm-trusted-firmware
make_atf(){
    cd $atf_dir
    #make realclean
    #echo "make CROSS_COMPILE=aarch64-openeuler-linux-gnu- PLAT=$platform"
    make CROSS_COMPILE=aarch64-openeuler-linux-gnu- PLAT=$platform
    
    cd -
    if [ ! -e "$atf_dir/build/$platform/release/bl31/bl31.elf" ]; then
        echo "错误: $atf_dir/build/$platform/release/bl31/bl31.elf 不存在"
        exit 1
    else
        cp $atf_dir/build/$platform/release/bl31/bl31.elf ./
    fi
}

generate_key() {
    rm dev.key dev.pubkey dev.crt
    rm privateKey.pem 
    rm public_key.pem
    openssl genrsa -out dev.key 2048
    openssl req -batch -new -x509 -key dev.key -out dev.crt
    openssl rsa -in dev.key -pubout -out dev.pubkey
}

make_secure_uboot(){
    cd $uboot_dir
    make clean
    export ROCKCHIP_TPL=$rkbin_dir/bin/rk35/rk3568_ddr_1560MHz_v1.11.bin
    export BL31=$atf_dir/build/$platform/release/bl31/bl31.elf
    #export BL31=/home/yanggan/secureboot/u-boot/rk3568_bl31_v1.32.elf
    export TEE=$rkbin_dir/bin/rk35/rk3568_bl32_v2.00.bin

    if [ ! -e "$ROCKCHIP_TPL" ]; then
        echo "错误: $ROCKCHIP_TPL 不存在"
        exit 1
    fi
    if [ ! -e "$BL31" ]; then
        echo "错误: $BL31 不存在"
        exit 1
    fi
    if [ ! -e "$TEE" ]; then
        echo "错误: $TEE 不存在"
        exit 1
    fi

    def_config=$uboot_config_dir/$make_config

    if ! grep -qF "CONFIG_FIT_EXTERNAL_OFFSET" "$def_config"; then
        echo "CONFIG_FIT_EXTERNAL_OFFSET=0x0E00" >> $def_config
    fi
    if ! grep -qF "CONFIG_FIT_SIGNATURE=y" "$def_config"; then
        echo "CONFIG_FIT_SIGNATURE=y" >> $def_config
    fi
    if ! grep -qF "CONFIG_FIT_RSASSA_PSS=y" "$def_config"; then
        echo "CONFIG_FIT_RSASSA_PSS=y" >> $def_config
    fi
    if ! grep -qF "CONFIG_SPL_FIT_SIGNATURE=y" "$def_config"; then
        echo "CONFIG_SPL_FIT_SIGNATURE=y" >> $def_config
    fi
    if ! grep -qF "CONFIG_SPL_FIT_RSASSA_PSS=y" "$def_config"; then
        echo "CONFIG_SPL_FIT_RSASSA_PSS=y" >> $def_config
    fi

    #生成.config 文件
    make $make_config

    #修改.config 里的内容

    sed -i "s/^CONFIG_FIT_EXTERNAL_OFFSET=.*/CONFIG_FIT_EXTERNAL_OFFSET=0x0E00/" .config
    #sed -i 's/^# CONFIG_FIT_SIGNATURE is not set/CONFIG_FIT_SIGNATURE=y/' .config
    #sed -i 's/^# CONFIG_FIT_RSASSA_PSS is not set/CONFIG_FIT_RSASSA_PSS=y/' .config
    #sed -i 's/^# CONFIG_SPL_FIT_SIGNATURE is not set/CONFIG_SPL_FIT_SIGNATURE=y/' .config
    #sed -i 's/^# CONFIG_SPL_FIT_RSASSA_PSS is not set/CONFIG_SPL_FIT_RSASSA_PSS=y/' .config 
    sed -i 's/^CONFIG_BOOTCOMMAND=.*/CONFIG_BOOTCOMMAND="part start mmc 0 3 kernel_start;part size mmc 0 3 kernel_size;mmc read $kernel_addr_c $kernel_start $kernel_size;bootm $kernel_addr_c"' .config
    
    #从.config中找到对应的设备
    #device_tree=$(grep CONFIG_DEFAULT_DEVICE_TREE= .config | cut -d '=' -f 2-)
    device_tree=$(grep "CONFIG_DEFAULT_DEVICE_TREE=" .config | cut -d '=' -f 2- | tr -d '"')
    device_tree=${device_tree}.dts
    echo "对应的设备树$device_tree"
    #对应的设备树插入公钥节点
    cd $dts_dir
    insert_line_number=$(awk '/\/dts-v1\/;/{ print NR; exit }' "$device_tree")
    insert_line="#include \"$public_key_path\""
    #如果设备树中没有插入公钥节点则插入
    if ! grep -qF "$insert_line" "$device_tree"; then
        sed -i "$insert_line_number a $insert_line" "$device_tree"
        echo "Insert line added successfully."
    else
        echo "Insert line already exists in the file."
    fi
    cd -

    make -j60 
    cp simple-bin.fit.fit $out_dir/uboot.img
}

make_uboot()
{
    cd $uboot_dir
    make clean
    export ROCKCHIP_TPL=$rkbin_dir/bin/rk35/rk3568_ddr_1560MHz_v1.11.bin
    export BL31=$atf_dir/build/$platform/release/bl31/bl31.elf
    #export BL31=/home/yanggan/secureboot/u-boot/rk3568_bl31_v1.32.elf
    export TEE=$rkbin_dir/bin/rk35/rk3568_bl32_v2.00.bin

    if [ ! -e "$ROCKCHIP_TPL" ]; then
        echo "错误: $ROCKCHIP_TPL 不存在"
        exit 1
    fi
    if [ ! -e "$BL31" ]; then
        echo "错误: $BL31 不存在"
        exit 1
    fi
    if [ ! -e "$TEE" ]; then
        echo "错误: $TEE 不存在"
        exit 1
    fi

    def_config=$uboot_config_dir/$make_config

    if  grep -qF "CONFIG_FIT_SIGNATURE=y" "$def_config"; then
        sed -i '/CONFIG_FIT_SIGNATURE=y/d' "$def_config"
    fi
    if  grep -qF "CONFIG_FIT_RSASSA_PSS=y" "$def_config"; then
        sed -i '/CONFIG_FIT_RSASSA_PSS=y/d' "$def_config"
    fi
    if  grep -qF "CONFIG_SPL_FIT_SIGNATURE=y" "$def_config"; then
        sed -i '/CONFIG_SPL_FIT_SIGNATURE=y/d' "$def_config"
    fi
    if  grep -qF "CONFIG_SPL_FIT_RSASSA_PSS=y" "$def_config"; then
        sed -i '/CONFIG_SPL_FIT_RSASSA_PSS=y/d' "$def_config"
    fi

    #生成.config 文件
    make $make_config
    sed -i "s/^CONFIG_FIT_EXTERNAL_OFFSET=.*/CONFIG_FIT_EXTERNAL_OFFSET=0x0E00/" .config
    #删除设备树中的公钥
    device_tree=$(grep "CONFIG_DEFAULT_DEVICE_TREE=" .config | cut -d '=' -f 2- | tr -d '"')
    device_tree=${device_tree}.dts
    echo "对应的设备树$device_tree"
    #对应的设备树插入公钥节点
    cd $dts_dir
    insert_line="#include \"$public_key_path\""
    #如果设备树中没有插入公钥节点则插入
    if  grep -qF "$insert_line" "$device_tree"; then
        echo "找到 $insert_line 并且删除"
        sed -i "$insert_line/d" "$device_tree" 
    else
        echo "没有找到 $insert_line "
    fi

    cd $uboot_dir
    make -j60 
    cp simple-bin.fit.fit $out_dir/uboot.img
}

fix_image_its(){
    common_h_dir=$uboot_dir/include/configs/rk3568_common.h

    #从头文件中获取到每个镜像要拷贝到内存的位置
    FDT_ADDR_R=`strings $common_h_dir | grep 'fdt_addr_r=' | awk -F "=" '{ print $2 }'`
    echo "FDT_ADDR_R: $FDT_ADDR_R"

    #fdt_addr_r=$(strings $common_h_dir | grep "fdt_addr_r=" | sed -e 's/.*=//' -e 's/\\0.*//')
    fdt_addr_r=0x08300000
    echo "fdt_addr_r: $fdt_addr_r"
    #kernel_addr_r=$(grep "kernel_addr_r=" "$common_h_dir" | sed -e 's/.*=//' -e 's/\\0.*//')
    kernel_addr_r=0x00280000
    echo "kernel_addr_r: $kernel_addr_r"
    #ramdisk_addr_r=$(grep "ramdisk_addr_r=" "$common_h_dir" | sed -e 's/.*=//' -e 's/\\0.*//')
    ramdisk_addr_r=0x0a200000
    echo "ramdisk_addr_r: $ramdisk_addr_r"

    sed -i "s/0xffffff00/$fdt_addr_r/g"      image.its
    sed -i "s/0xffffff01/$kernel_addr_r/g"   image.its
    sed -i "s/0xffffff02/$ramdisk_addr_r/g"  image.its
    #直接修改image.its 文件
  #  sed -i "s/0xffffff00/${fdt_addr_r}/g" image.its
   # sed -i "s/0xffffff01/${kernel_addr_r}/g" image.its
   # sed -i "s/0xffffff02;/${ramdisk_addr_r}/g" image.its

    cat image.its
}

sign_boot(){
    cd $work_dir

    # 检查 boot.img 是否存在
    if [ ! -e "$boot_img" ]; then
        echo "错误: $boot_img 不存在"
        exit 1
    fi
    if [ ! -e "$key_dir/dev.key" ]; then
        echo "错误: $key_dir/dev.key 不存在"
        exit 1
    fi

    #解压boot.img 到临时文件家upack_fit_boot中
    $tool_dir/fit-unpack.sh -f $boot_img -o upack_fit_boot
    cd upack_fit_boot/

    #生成一个空设备树二进制文件dtb文件用来保存生成的公钥
    create_empty_dtb

    #image.its 文件中的内存地址信息要瑞芯微没填入，这里必须填入，否则boot.img起不来
    fix_image_its

    #使用mkimage 指令重新打包boot.img并且进行签名，用于验签的公钥会输出到pub-key.dtb文件中
    #mkimage -k $key_dir -f image.its -K pub-key.dtb -E -p 0xE00 -r  ../boot_sign.img
    mkimage -k $key_dir -f image.its -K pub-key.dtb -E -p 0xE00 -r  $out_dir/boot_sign.img
    mkimage -f image.its  -E -p 0xE00 -r  $out_dir/boot.img
    #将设备树二进制文件pub-key.dtb转换成设备树源文件public_key.dts
    dtc -I dtb -O dts pub-key.dtb -o $public_key_path
    cd -
    #./tools/fit_check_sign -f boot_sign.img -k ./upack_fit_boot/pub-key.dtb
 #   rm -rf upack_fit_boot
}

insert_signature() {
    local file="$1"
    local sign_string='\
                        signature {\
                            algo = "sha256,rsa2048";\
                            padding = "pss";\
                            key-name-hint = "dev";\
                            sign-images = "fdt\\0firmware\\0loadables";\
                        };\
    '
    default_value=$(grep -A 1 "configurations {" $file | grep "default =" | awk -F "=" '{print $2}' | tr -d '[:space:]')
    default_value=$(echo "$default_value" | sed 's/"//g' | sed 's/;//g')
    configurations_line=$(grep -n 'configurations' $file | cut -d':' -f1)
    echo "configurations_line=$configurations_line"
    #config_line=$(tail -n +100 file.txt | grep -n "config-1" | awk -F ":" '{print $1}')
    config_line=$(grep -n "$default_value {" $file | cut -d':' -f1)
    echo "config_line=$config_line"
    insert_line=$(tail -n +$config_line $file | grep -m 1 -n "}" | awk -F ":" '{print $1}')
    echo "insert_line=$insert_line"
    insert_line=$((insert_line + config_line-1))
    echo "insert_line=$insert_line"

    sed -i "${insert_line}s/^/${sign_string}/" image.its
    cat -n image.its
}

sign_uboot(){
    cd $uboot_dir
    rm -rf upack_fit_uboot
    #解压uboot镜像
    $tool_dir/fit-unpack.sh -f  simple-bin.fit.fit -o upack_fit_uboot
    cd upack_fit_uboot/

    #对Image.its 插入签名节点
    insert_signature "image.its"
    create_empty_dtb
    # 在 image.its 文件中添加 signature 节点和属性
    mkimage -k $key_dir -f image.its -K pub-key.dtb -r $out_dir/uboot_sign.img
    cd -
    #./tools/fit_check_sign -f uboot_sign.img -k ./upack_fit_uboot/pub-key.dtb
}

function sign_mimiloader()
{
    echo "开始签名idbloader"
    RK_SIGN_TOOL=$rkbin_dir/tools/rk_sign_tool
    ARG_CHIP=RK3568
    #RSA_PRI_KEY=$key_dir/privateKey.pem
    #RSA_PUB_KEY=$key_dir/publicKey.pem
    RSA_PRI_KEY=$key_dir/dev.key
    RSA_PUB_KEY=$key_dir/dev.pubkey
    ${RK_SIGN_TOOL} CC --chip ${ARG_CHIP: 2: 6}
    ${RK_SIGN_TOOL} sl --key ${RSA_PRI_KEY} --pubkey ${RSA_PUB_KEY} --loader *loader*.bin
#	if grep -Eq '^CONFIG_FIT_SIGNATURE=y' .config ; then
#    ${RK_SIGN_TOOL} CC --chip ${ARG_CHIP: 2: 6}
 #   ${RK_SIGN_TOOL} LK --key ${RSA_PRI_KEY} --pubkey ${RSA_PUB_KEY}
 #   if ls *loader*.bin >/dev/null 2>&1 ; then
 #       ${RK_SIGN_TOOL} sl --loader *loader*.bin
 #   fi
 #   if ls *download*.bin >/dev/null 2>&1 ; then
 #       ${RK_SIGN_TOOL} sl --loader *download*.bin
 #   fi
 #   if ls *idblock*.img >/dev/null 2>&1 ; then
  #      ${RK_SIGN_TOOL} sb --idb *idblock*.img
  #  fi
#	fi
}

sign_idbloader(){
    echo "开始打包idbloader"
    cd $rkbin_dir
    rm tmp -rf && mkdir tmp -p
    rm *spl_loader_*.bin
    cp ./RKBOOT/RK3568MINIALL.ini ./tmp/miniloader.ini
    cp $uboot_dir/spl/u-boot-spl.bin ./tmp/u-boot-spl.bin
    #cp $rkbin_dir/bin/rk35/rk356x_spl_v1.11.bin ./tmp/u-boot-spl.bin
	sed -i "s/FlashBoot=.*$/FlashBoot=.\/tmp\/u-boot-spl.bin/" ./tmp/miniloader.ini
    $rkbin_dir/tools/boot_merger ./tmp/miniloader.ini
    mv *spl_loader_*.bin $work_dir/
    cd $work_dir/
    cp *spl_loader_*.bin $out_dir/MiniLoaderAll.bin
    sign_mimiloader
    mv *spl_loader_*.bin $out_dir/MiniLoaderAll_sign.bin
}

build_update_img(){
    name=$1
    cd $update_img_build_dir
    ./afptool -pack ./ Image/update.img
    ./rkImageMaker -RK3568 Image/MiniLoaderAll.bin Image/update.img $out_dir/$name -os_type:androidos
    rm Image/update.img
}

build_sign_update_img(){
    sign_boot
    make_secure_uboot
    sign_uboot
    sign_idbloader
    rm $out_dir/update_sign.img
    cd $update_img_build_dir
    cp $out_dir/MiniLoaderAll_sign.bin Image/MiniLoaderAll.bin
    cp $out_dir/uboot_sign.img Image/uboot.img
    cp $out_dir/boot_sign.img Image/boot.img
    build_update_img update_sign.img
}

build_unsign_update_img(){
    sign_boot
    make_uboot
    sign_idbloader
    rm $out_dir/update.img
    cd $update_img_build_dir
    cp $out_dir/MiniLoaderAll_sign.bin Image/MiniLoaderAll.bin
    cp $uboot_dir/simple-bin.fit.fit Image/uboot.img
    cp $out_dir/boot.img Image/boot.img
    build_update_img update.img
}

testall(){
    sign_boot
    make_secure_uboot
    sign_uboot
    sign_idbloader
    #生成完整签名的update.img
    build_sign_update_img
    #生成boot.img 没签名，但是idbloader和uboot都签名的update.img
    cp $out_dir/boot.img Image/boot.img
    build_update_img "unsign_boot-update.img"
    cp $out_dir/uboot.img Image/uboot.img
    build_update_img "unsign_uboot-update.img"
    cp $out_dir/MiniLoaderAll.bin Image/MiniLoaderAll.bin
    build_update_img "unsign_idbloder-update.img"
}
check_uboot_sign(){
    ./tools/fit_check_sign -f uboot_sign.img -k ./spl/dts/dt-spl.dtb
}

check_boot_sign(){
     ./tools/fit_check_sign -f boot_sign.img -k ./dts/dt.dtb
}

function help()
{
	echo
	echo "Usage:"
	echo "	./make.sh [board|sub-command]"
	echo
	echo "	 - board:        board name of defconfig"
	echo "	 - sub-command:  elf*|loader|trust|uboot|--spl|--tpl|itb|map|sym|<addr>"
	echo "	 - ini:          ini file to pack trust/loader"
	echo
	echo "Output:"
	echo "	 When board built okay, there are uboot/trust/loader images in current directory"
	echo
	echo "Example:"
	echo
	echo "1. Build:"
	echo "	./make.sh evb-rk3399               --- build for evb-rk3399_defconfig"
	echo "	./make.sh firefly-rk3288           --- build for firefly-rk3288_defconfig"
	echo "	./make.sh EXT_DTB=rk-kernel.dtb    --- build with exist .config and external dtb"
	echo "	./make.sh                          --- build with exist .config"
	echo "	./make.sh env                      --- build envtools"
	echo
	echo "2. Pack:"
	echo "	./make.sh uboot                    --- pack uboot.img"
	echo "	./make.sh trust                    --- pack trust.img"
	echo "	./make.sh trust <ini>              --- pack trust img with assigned ini file"
	echo "	./make.sh loader                   --- pack loader bin"
	echo "	./make.sh loader <ini>             --- pack loader img with assigned ini file"
	echo "	./make.sh --spl                    --- pack loader with u-boot-spl.bin"
	echo "	./make.sh --tpl                    --- pack loader with u-boot-tpl.bin"
	echo "	./make.sh --tpl --spl              --- pack loader with u-boot-tpl.bin and u-boot-spl.bin"
	echo
	echo "3. Debug:"
	echo "	./make.sh elf                      --- dump elf file with -D(default)"
	echo "	./make.sh elf-S                    --- dump elf file with -S"
	echo "	./make.sh elf-d                    --- dump elf file with -d"
	echo "	./make.sh elf-*                    --- dump elf file with -*"
	echo "	./make.sh <no reloc_addr>          --- unwind address(no relocated)"
	echo "	./make.sh <reloc_addr-reloc_off>   --- unwind address(relocated)"
	echo "	./make.sh map                      --- cat u-boot.map"
	echo "	./make.sh sym                      --- cat u-boot.sym"
}

#./tools/fit_check_sign -f ./keys/boot_sign.img -k ./dts/upstream/src/arm64/rockchip/rk3568-evb1-v10.dtb
# 检查输入参数并执行相应函数
if [ "$1" == "create_empty_dtb" ]; then
    create_empty_dtb

elif [ "$1" == "make_atf" ]; then
    make_atf

elif [ "$1" == "generate_key" ]; then
    generate_key

elif [ "$1" == "make_secure_uboot" ]; then
    make_secure_uboot

elif [ "$1" == "make_uboot" ]; then
    make_uboot

elif [ "$1" == "sign_boot" ]; then
    sign_boot

elif [ "$1" == "sign_uboot" ]; then
    sign_uboot

elif [ "$1" == "sign_idbloader" ]; then
    sign_idbloader

elif [ "$1" == "build_update_img" ]; then
    build_update_img

elif [ "$1" == "sign_img" ]; then
    build_sign_update_img

elif [ "$1" == "unsign_img" ]; then
    build_unsign_update_img

elif [ "$1" == "testall" ]; then
    testall

elif [ "$1" == "clean" ]; then
    rm *.dtb *.dts -rf
    rm uboot.img uboot_sign.img update.img update_sign.img  rk356x_spl_loader_v1.11.111.bin boot_sign.img
    rm -rf output
    cd $uboot_dir
    make clean
    cd $atf_dir
    make realclean
    cd $work_dir
else
   # help()
    exit 1
fi


